/**
 * 
 */
package simulation;

import static common.PathJoin.pathJoin;
import static common.Todouble.todouble;

import java.util.ArrayList;
import java.util.Date;

import org.apache.commons.math.stat.StatUtils;

/**
 * @author vladimir
 * 
 */
public class Main_discrete {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// Parameters
		// Neighbors in spatial direction
		int[][] neighbors = { { 0, 1 }, { 0, -1 }, { 1, 0 }, { -1, 0 },
				{ -1, -1 }, { 1, 1 } };
		String modelName = "triang_discrete";
		// int[][] neighbors = { { 0, 1 }, { 0, -1 }, { 1, 0 }, { -1, 0 } };
		// String modelName = "square_discrete";

		// int[][] neighbors = { { 1 }, { -1 } };
		// String modelName = "chain_discrete";

		// spatial coupling constant
		double J = 1;
		// double epsilon = 0.1;

		// Array describing size of the lattice
		int[] lRange = { 3 };

		// Array describing temperature
		double[] tRange = common.Range.range(0.5, 6, 0.01);
		// double[] tRange = { 0.5 };
		// Array describing Magnetic field
		// double[] bRange = { 1, 2, 3, 4 };
		double[] bRange = { 1 };

		boolean info = true;

		for (int L : lRange) {
			for (double B : bRange) {// go through different magnetic field
										// values
				for (double T : tRange) {// go through different temperatures
					java.util.Date Idate = new Date();
					CorrTime_discrete Cor = new CorrTime_discrete(neighbors, J,
							L, B, T, modelName);

					Lattice_discrete Lat = Cor.Lat;

					int MCS = -1;
					int Thermal_MCS = -1;
					if (Cor.ThermalMCS() > Cor.mcs) {
						// number of the Monte Carlo Sweeps
						MCS = Cor.MCS() - Cor.mcs;
						// number of the Monte Carlo Sweeps to reach equilibrium
						Thermal_MCS = Cor.ThermalMCS() - Cor.mcs;
					} else {
						// number of the Monte Carlo Sweeps
						MCS = Cor.MCS() - Cor.ThermalMCS();
						// number of the Monte Carlo Sweeps to reach equilibrium
						Thermal_MCS = 0;
					}

					// Correlation time
					int sweepStep = Cor.SweepStep();
					// int sweepStep = 1;

					ArrayList<Double> tE = new ArrayList<Double>();
					ArrayList<Double> tM = new ArrayList<Double>();
					ArrayList<Double> tM2 = new ArrayList<Double>();
					ArrayList<Double> tM4 = new ArrayList<Double>();

					if (info) {
						System.out.println();
						System.out.println("model : " + modelName);
						System.out.println("J - " + J);
						System.out.println("L - " + L);
						System.out.println("B - " + B);
						System.out.println("T - " + T);

						System.out.println("Monte Carlo Sweeps - " + Cor.MCS());

						System.out.println("Thermal Monte Carlo Sweeps - "
								+ Cor.ThermalMCS());
						System.out.println("Correlation time - " + sweepStep);
					}
					for (int sweep = 0; sweep < MCS; sweep++) {
						Lat.update();
						if ((Thermal_MCS < sweep) && (sweep % sweepStep == 0)) {
							tE.add(Lat.Energy());
							double M = Lat.M();
							tM.add(Math.abs(M));
							tM2.add(M * M);
							tM4.add(Math.pow(M, 4));
						}
					}

					// System.out.println("tE length : " + tE.size());
					// save data to file
					common.FSave.fSave(
							pathJoin("results", modelName, "J_" + J, "B_" + B,
									"L_" + L, "Energy"), "T" + T, StatUtils
									.mean(todouble(tE)));

					common.FSave.fSave(
							pathJoin("results", modelName, "J_" + J, "B_" + B,
									"L_" + L, "M"), "T" + T, StatUtils
									.mean(todouble(tM)));

					common.FSave.fSave(
							pathJoin("results", modelName, "J_" + J, "B_" + B,
									"L_" + L, "M2"), "T" + T, StatUtils
									.mean(todouble(tM2)));

					common.FSave.fSave(
							pathJoin("results", modelName, "J_" + J, "B_" + B,
									"L_" + L, "M2"), "T" + T, StatUtils
									.mean(todouble(tM4)));

					common.FSave.fSave(
							pathJoin("results", modelName, "J_" + J, "B_" + B,
									"L_" + L, "autoCorrelationTime"), "T" + T,
							Cor.SweepStep());

					if (info) {
						java.util.Date Fdate = new Date();
						long timeDiff = Fdate.getTime() - Idate.getTime();
						System.out.println("Waste of time: " + timeDiff);
					}

				}
			}
		}
	}
}
